#!/usr/bin/env sh
# vim: filetype=sh:tabstop=2:tw=100:expandtab
# SPDX-License-Identifier: MIT-0
# scspell-id: 6fefda68-f778-11ec-85a4-80ee73e9b8e7
# Copyright (c) 2021-2025 The DPS8M Development Team

####################################################################################################

set +e > /dev/null 2>&1
set -u > /dev/null 2>&1

####################################################################################################

# shellcheck disable=SC2015
test -z "${VERBOSE_HOOK:-}" &&
  {
    set +x 2> /dev/null;
  } || {
    set -x 2> /dev/null;
  };

####################################################################################################

# shellcheck disable=SC2015
test -z "${DEBUG_HOOK:-}" &&
  {
    DEBUG_CALL="true";
  } || {
    DEBUG_CALL="echo";
  };

####################################################################################################

# shellcheck disable=SC2015
test -z "${EXTRA_HOOK:-}" &&
  {
    HOOK_CALL="${GIT:-git} diff --cached --name-only";
  } || {
    test -n "${MAKE_HOOK:-}" &&
    {
      HOOK_CALL="${GIT:-git} ls-files";
    } || {
      HOOK_CALL="find . -print";
    };
  };
test -z "${VERBOSE_HOOK:-}" || ${DEBUG_CALL:?} HOOK_CALL is "${HOOK_CALL:?}" ...

####################################################################################################

if [ -n "${MAKE_HOOK:-}" ] && [ -n "${EXTRA_HOOK:-}" ]; then
    ${DEBUG_CALL:?} Running checks on all committed tracked files ...
elif [ -n "${MAKE_HOOK:-}" ] && [ -z "${EXTRA_HOOK:-}" ]; then
    ${DEBUG_CALL:?} Running checks on uncommitted changes ...
fi

####################################################################################################

# shellcheck disable=SC2015
test -z "${SKIP_HOOK:-}" &&
  {
    EXIT_STATUS=1;
  } || {
    EXIT_STATUS=0;
  };
test -z "${VERBOSE_HOOK:-}" || ${DEBUG_CALL:?} EXIT_STATUS is ${EXIT_STATUS:?} ...

####################################################################################################

${DEBUG_CALL:?} Finding git toplevel ...
cd "$(${GIT:-git} rev-parse --show-toplevel)" ||
  {
    printf '%s\n' "ERROR: Unable to find git toplevel!" >&2;
    exit "${EXIT_STATUS:-1}";
  };

####################################################################################################

${DEBUG_CALL:?} Check for spaces in new filenames ...
if (${HOOK_CALL:?} | awk '{ print "\""$0"\"" }' | grep ' ' >&2); then
  {
    printf '%s\n' "ERROR: Filename check failed due to spaces!" >&2;
    exit "${EXIT_STATUS:-1}";
  };
fi

####################################################################################################

${DEBUG_CALL:?} Checking git diff-check ...
${GIT:-git} diff --check >&2 ||
  {
    printf '%s\n' "ERROR: git diff-check failed!" >&2
    exit "${EXIT_STATUS:-1}"
  };

####################################################################################################

${DEBUG_CALL:?} Checking Cppi indentation ...
if (command -v cppi > /dev/null 2>&1); then
  CPPISCAN="$(${MAKE:-make} cppiscan 2> /dev/null | grep '/' | \
    grep -Eiv '(^libuv|^src/libsir|^src/libbacktrace)' || true)"
  test -z "${CPPISCAN:-}" ||
    {
      printf '%s\n' "${CPPISCAN:?}" >&2;
      printf '%s\n' "ERROR: Cppi check failed!" >&2;
      printf '%s\n' "       (Try \"${MAKE:-make} cppifix\" for auto fix)" >&2;
      exit "${EXIT_STATUS:-1}";
    };
else
  printf '%s\n' 'WARNING: "cppi" not found in PATH - some checks skipped!' >&2;
fi

####################################################################################################

${DEBUG_CALL:?} Checking for tabs in C source code files ...
TLIST="$(${HOOK_CALL:?} | grep '\.[ch]$' | \
  grep -Ev '(src/libsir/|src/libbacktrace)' | \
    xargs -L 1 grep -l "$(printf '\t')" 2> /dev/null)";
printf "%s\n" "${TLIST:-}" | grep -v '^$' 2> /dev/null | grep . >&2 &&
  {
    printf '%s\n' "ERROR: Tabs check failed!" >&2;
    exit "${EXIT_STATUS:-1}";
  }

####################################################################################################

${DEBUG_CALL:?} Checking for FREE misuse in C source code files ...
TLIST="$(${HOOK_CALL:?} | grep '\.[ch]$' | xargs -I{} | \
  grep -Ev '(src/libsir/|src/libbacktrace)' | \
    grep -HEn '( free \(| free\(|^free \(|^free\()' "{}" 2> /dev/null | \
      grep -Ev '(FREE|free\(\(p\)\).*\\$)' 2> /dev/null || true 2> /dev/null)";
printf "%s\n" "${TLIST:-}" | grep -v '^$' 2> /dev/null | grep . >&2 &&
  {
    printf '%s\n' "ERROR: FREE check failed!" >&2;
    exit "${EXIT_STATUS:-1}";
  }

####################################################################################################

${DEBUG_CALL:?} Checking for strerror misuse in C source code files ...
TLIST="$(${HOOK_CALL:?} | grep '\.[ch]$' | \
  grep -Ev '(src/libsir/|src/libbacktrace)' | xargs -I{} \
    grep -HEn 'strerror' "{}" 2> /dev/null | \
      grep -Ev '(xstrerror_l|uv_strerror|LINTOK )' 2> /dev/null || true 2> /dev/null)";
printf "%s\n" "${TLIST:-}" | grep -v '^$' 2> /dev/null | grep . >&2 &&
  {
    printf '%s\n' "ERROR: strerror check failed!" >&2;
    exit "${EXIT_STATUS:-1}";
  }
####################################################################################################

${DEBUG_CALL:?} Checking for trailing whitespace ...
TLIST="$(${HOOK_CALL:?} | \
 grep -Ev '(src/libsir/|src/libbacktrace/|mcmb$|unifdef$|tags$|prt2pdf$|GRTAGS$|GTAGS$)' |
  grep -Ev '(punutil$|dps8$|l68$|empty$|\.out$|\.tmp$|~$|\.exe$|\.dll$|\.o$|core$|\.git/.)' |
   grep -Ev '(strip\.mem$|bound_library_wired_$|ci_full\.log\.ref$|\.woff$|\.woff2$|\.png$|\.jpg$)' |
   xargs -I{} grep -ial ' \+$' "{}" 2> /dev/null)";
printf "%s\n" "${TLIST:-}" | grep -v '^$' 2> /dev/null | grep . >&2 &&
  {
    printf '%s\n' "ERROR: Trailing whitespace check failed!" >&2;
    exit "${EXIT_STATUS:-1}";
  }

####################################################################################################

test -z "${TEST_DEPENDS:-}" ||
  {
    ${DEBUG_CALL:?} Regenerating dependencies ...
    ${MAKE:-make} "depend" > /dev/null 2>&1;
    ${DEBUG_CALL:?} Checking for uncommited changes ...
    UCHNG="$(${GIT:-git} diff 2>&1)";
    printf "%s\n" "${UCHNG:-}" | grep . >&2 &&
      {
        printf '%s\n' "ERROR: Uncommited changes found (after dependency regeneration)!" >&2;
        exit "${EXIT_STATUS:-1}";
      }
  }

####################################################################################################

${DEBUG_CALL:?} Completed pre-commit hook ...
exit 0;

####################################################################################################
